#include <iostream>
#include <cmath>
#include <portaudio.h>
#include <thread>
#include <chrono>

// 列出所有音频设备
void list_audio_devices() {
    PaError err = Pa_Initialize();
    if (err != paNoError) {
        std::cerr << "PortAudio error: " << Pa_GetErrorText(err) << std::endl;
        return;
    }

    int numDevices = Pa_GetDeviceCount();
    if (numDevices < 0) {
        std::cerr << "Error getting device count: " << Pa_GetErrorText(numDevices) << std::endl;
        return;
    }

    std::cout << "\n可用音频设备列表:\n";
    for (int i = 0; i < numDevices; i++) {
        const PaDeviceInfo* deviceInfo = Pa_GetDeviceInfo(i);
        std::cout << "设备 " << i << ": " << deviceInfo->name;
        
        // 显示设备类型
        if (deviceInfo->maxInputChannels > 0 && deviceInfo->maxOutputChannels > 0) {
            std::cout << " (输入/输出设备)";
        } else if (deviceInfo->maxInputChannels > 0) {
            std::cout << " (输入设备)";
        } else if (deviceInfo->maxOutputChannels > 0) {
            std::cout << " (输出设备)";
        }
        
        std::cout << std::endl;
    }

    Pa_Terminate();
}

// 音频回调函数
static int audioCallback(const void* inputBuffer, void* outputBuffer,
                         unsigned long framesPerBuffer,
                         const PaStreamCallbackTimeInfo* timeInfo,
                         PaStreamCallbackFlags statusFlags,
                         void* userData) {
    // 获取用户数据
    double* data = static_cast<double*>(userData);
    double frequency = data[0];
    double amplitude = data[1];
    double phase = data[2];
    
    // 输出缓冲区
    float* out = static_cast<float*>(outputBuffer);
    
    // 计算每个采样的相位增量
    double phaseIncrement = 2.0 * M_PI * frequency / 44100.0;
    
    // 生成音频信号
    for (unsigned int i = 0; i < framesPerBuffer; i++) {
        // 计算正弦波值
        float sample = amplitude * sin(phase);
        
        // 写入左右声道
        *out++ = sample; // 左声道
        *out++ = sample; // 右声道
        
        // 更新相位
        phase += phaseIncrement;
        
        // 保持相位在0-2π范围内
        if (phase >= 2.0 * M_PI) {
            phase -= 2.0 * M_PI;
        }
    }
    
    // 保存当前相位
    data[2] = phase;
    
    return paContinue;
}

int main() {
    double frequency, amplitude;
    int outputDeviceIndex;
    
    // 获取用户输入
    std::cout << "请输入纯音频率 (Hz): ";
    std::cin >> frequency;
    
    std::cout << "请输入音量幅度 (0.0 - 1.0): ";
    std::cin >> amplitude;
    
    // 限制幅度在合理范围内
    amplitude = std::max(0.0, std::min(1.0, amplitude));
    
    // 列出并选择设备
    list_audio_devices();
    std::cout << "\n请选择输出设备编号: ";
    std::cin >> outputDeviceIndex;
    
    // 初始化PortAudio
    PaError err = Pa_Initialize();
    if (err != paNoError) {
        std::cerr << "PortAudio初始化失败: " << Pa_GetErrorText(err) << std::endl;
        return 1;
    }
    
    // 检查设备索引是否有效
    int numDevices = Pa_GetDeviceCount();
    if (outputDeviceIndex < 0 || outputDeviceIndex >= numDevices) {
        std::cerr << "无效的设备索引" << std::endl;
        Pa_Terminate();
        return 1;
    }
    
    // 获取设备信息
    const PaDeviceInfo* deviceInfo = Pa_GetDeviceInfo(outputDeviceIndex);
    if (deviceInfo->maxOutputChannels < 2) {
        std::cerr << "所选设备不支持立体声输出" << std::endl;
        Pa_Terminate();
        return 1;
    }
    
    // 设置输出参数
    PaStreamParameters outputParameters;
    outputParameters.device = outputDeviceIndex;
    outputParameters.channelCount = 2; // 立体声
    outputParameters.sampleFormat = paFloat32;
    outputParameters.suggestedLatency = deviceInfo->defaultLowOutputLatency;
    outputParameters.hostApiSpecificStreamInfo = nullptr;
    
    // 用户数据：频率、幅度、相位
    double userData[3] = {frequency, amplitude, 0.0};
    
    // 打开音频流
    PaStream* stream;
    err = Pa_OpenStream(
        &stream,
        nullptr, // 无输入
        &outputParameters,
        44100, // 采样率
        256,   // 帧缓冲区大小
        paClipOff,
        audioCallback,
        userData
    );
    
    if (err != paNoError) {
        std::cerr << "无法打开音频流: " << Pa_GetErrorText(err) << std::endl;
        Pa_Terminate();
        return 1;
    }
    
    // 启动音频流
    err = Pa_StartStream(stream);
    if (err != paNoError) {
        std::cerr << "无法启动音频流: " << Pa_GetErrorText(err) << std::endl;
        Pa_CloseStream(stream);
        Pa_Terminate();
        return 1;
    }
    
    std::cout << "正在播放 " << frequency << " Hz 纯音 (" << amplitude * 100 << "% 音量)..." << std::endl;
    
    // 播放1分钟
    std::this_thread::sleep_for(std::chrono::seconds(60));
    
    // 停止音频流
    err = Pa_StopStream(stream);
    if (err != paNoError) {
        std::cerr << "无法停止音频流: " << Pa_GetErrorText(err) << std::endl;
    }
    
    // 关闭音频流
    err = Pa_CloseStream(stream);
    if (err != paNoError) {
        std::cerr << "无法关闭音频流: " << Pa_GetErrorText(err) << std::endl;
    }
    
    // 终止PortAudio
    Pa_Terminate();
    
    std::cout << "播放完成！" << std::endl;
    
    return 0;
}